package view.editor;

import java.awt.Component;
import java.awt.Point;
import java.awt.SystemColor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Enumeration;
import java.util.Iterator;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;

import main.model.Diagram;
import main.model.Entity;
import main.model.Hierarchy;
import main.model.Relation;
import view.Displayable;
import view.View;

import com.mxgraph.model.mxCell;
import com.mxgraph.swing.mxGraphComponent;

import controller.editor.EditorController;
import controller.editor.ProjectExplorerController;

public class EditorView extends View<EditorController> implements Displayable {

	private EditorController controller;
	
	private JFrame frame;
	
	private mxGraphComponent graphComponent;
	
	private JTree tree;
	
	private JPanel drawingArea;
	
	private JPanel buttonPanel;
	
	/**
	 * Create the application.
	 */
	public EditorView(EditorController controller) {
		this.controller = controller;
		initialize();
	}

	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() {
		setFrame(new JFrame("Editor"));
//		getFrame().setResizable(Boolean.FALSE);
        getFrame().setExtendedState(JFrame.MAXIMIZED_BOTH);  
		getFrame().setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		buttonPanel = new JPanel();
		buttonPanel.setBounds(12, 12, 1277, 43);
		
		drawingArea = new JPanel();
		drawingArea.setBounds(184, 47, 1105, 685);
		setGraphComponent(new mxGraphComponent(CanvasView.getInstance()));
		getGraphComponent().getGraphControl().addMouseListener(controller.getMouseListener());
		getGraphComponent().getGraphControl().addMouseMotionListener(controller.getMouseMotionListener());
		drawingArea.setLayout(null);
		getGraphComponent().setBounds(0, 0, 1179, 695);
		getGraphComponent().getViewport().setBackground(SystemColor.WHITE);
		drawingArea.add(getGraphComponent());
		CanvasView.getInstance().setGraphComponent(this.getGraphComponent());
		drawingArea.setLayout(null);
		
		JButton btnGuardar = new JButton("Guardar");
		btnGuardar.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				getController().handleButtonSave();
			}
		});
		buttonPanel.add(btnGuardar);
		
		JButton btnImprimir = new JButton("Imprimir");
		btnImprimir.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				getController().handleButtonPrint();
			}
		});
		buttonPanel.add(btnImprimir);
		
		JButton btnExportar = new JButton("Exportar");
		btnExportar.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				getController().handleButtonExportar();
			}
		});
		buttonPanel.add(btnExportar);
		
		JButton btnEntidad = new JButton("Entidad");
		btnEntidad.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				getController().handleButtonEntity();
			}
		});
		buttonPanel.add(btnEntidad);
		
		JButton btnRelacion = new JButton("Relacion");
		btnRelacion.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				getController().handleButtonRelation();
			}
		});
		buttonPanel.add(btnRelacion);
		
		JButton btnJerarquia = new JButton("Jerarquia");
		btnJerarquia.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				getController().handleButtonJerarquia();
			}
		});
		buttonPanel.add(btnJerarquia);
		
		JButton btnValidar = new JButton("Validar");
		btnValidar.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				getController().handleButtonValidar();
			}
		});
		buttonPanel.add(btnValidar);
		
		JButton btnNuevoDiagrama = new JButton("Nuevo Diagrama");
		buttonPanel.add(btnNuevoDiagrama);
		btnNuevoDiagrama.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				getController().handleButtonNuevoDiagrama();
			}
		});
		
		JButton btnGuardarTodo = new JButton("Guardar Todo");
		buttonPanel.add(btnGuardarTodo);
		btnGuardarTodo.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				getController().handleButtonGuardarTodos();
			}
		});
		
		JButton btnSalir = new JButton("Salir");
		btnSalir.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				getController().handleButtonSalir();
			}
		});
		buttonPanel.add(btnSalir);
		
		
		
		frame.getContentPane().setLayout(null);
		
		JScrollPane scrollPane = new JScrollPane();
		scrollPane.setBounds(12, 47, 160, 685);
		DefaultMutableTreeNode top =
			        new DefaultMutableTreeNode(this.getController().getProject().getName());
		for (Diagram d : this.getController().getProject().getDiagrams()) {
			DefaultMutableTreeNode sub =
			        new DefaultMutableTreeNode(d.getName());
			top.add(sub);
		} 
		this.setTree(new JTree(top));
		this.getTree().setBackground(UIManager.getColor("Button.background"));
		this.getTree().addTreeSelectionListener(new ProjectExplorerController(this.getTree(), this));
		this.addTreeListener();
		scrollPane.setViewportView(this.getTree());
		frame.getContentPane().add(buttonPanel);
		
		JSplitPane splitPane = new JSplitPane();
		splitPane.setOneTouchExpandable(true);
		splitPane.setBounds(12, 67, 1262, 665);
		splitPane.setLeftComponent(scrollPane);
		splitPane.setRightComponent(drawingArea);
		frame.getContentPane().add(splitPane);
	}

	private void addTreeListener() {
		this.tree.addMouseListener(this.controller.getTreeMouseListener());
	}

	private void setTree(JTree jTree) {
		this.tree = jTree;
	}

	@Override
	public void show() {
		getFrame().setVisible(true);
	}
	
	@Override
	public void hide() {
		getFrame().setVisible(false);
	}

	public JFrame getFrame() {
		return frame;
	}

	public void setFrame(JFrame frame) {
		this.frame = frame;
	}

	@Override
	public EditorController getController() {
		return this.controller;
	}

	@Override
	public void setController(EditorController controller) {
		this.controller = controller;
	}
	
	public Component getComponent(){
		return this.getGraphComponent().getGraphControl();
	}

	public void drawEntity(Entity entity, Point point) {
		CanvasView.getInstance().drawEntity(entity, point);
	}

	public void drawRelation(Relation rel) {
		CanvasView.getInstance().drawRelation(rel);
	}

	public void addNewDiagramToTree(String diagramName) {
		DefaultTreeModel model = (DefaultTreeModel)this.getTree().getModel();
		DefaultMutableTreeNode root = (DefaultMutableTreeNode)model.getRoot();
		root.add(new DefaultMutableTreeNode(diagramName));
		model.reload(root);
	}

	public void addNewLeafToDiagram(String name) {
		DefaultTreeModel model = (DefaultTreeModel)this.getTree().getModel();
		DefaultMutableTreeNode nodeToAdd = this.searchNode(this.controller.getCurrentDiagram().getName());
		nodeToAdd.add(new DefaultMutableTreeNode(name));
		model.reload(nodeToAdd);
	}
	
	@SuppressWarnings("rawtypes")
	private DefaultMutableTreeNode searchNode(String nodeStr) {
		DefaultTreeModel model = (DefaultTreeModel)this.getTree().getModel();
		DefaultMutableTreeNode m_rootNode = (DefaultMutableTreeNode)model.getRoot();
	    DefaultMutableTreeNode node = null;
	    Enumeration e = m_rootNode.breadthFirstEnumeration();
	    while (e.hasMoreElements()) {
	      node = (DefaultMutableTreeNode) e.nextElement();
	      if (nodeStr.equals(node.getUserObject().toString())) {
	        return node;
	      }
	    }
	    return null;
	  }

	public JTree getTree() {
		return tree;
	}
	
	public void cleanScreen(){
		CanvasView.getInstance().selectAll();
		CanvasView.getInstance().removeCells(CanvasView.getInstance().getSelectionCells());
	}
	
	public void drawDiagram(Diagram d){
		Iterator<Entity> entitiesIt = d.getEntities().iterator();
		while (entitiesIt.hasNext()){
			Entity entity = entitiesIt.next();
			Point ePoint = this.controller.getPointForComponent(entity);
			CanvasView.getInstance().repaintEntity(entity, ePoint);
		}
		Iterator<Relation> relationIt = d.getRelations().iterator();
		while (relationIt.hasNext()){
			Relation relation = relationIt.next();
			Point rPoint = this.controller.getPointForComponent(relation);
			CanvasView.getInstance().repaintRelation(relation, rPoint);
		}
		Iterator<Hierarchy> hierarchyIt = d.getHierarchies().iterator();
		while (hierarchyIt.hasNext()){
			Hierarchy hierarchy = hierarchyIt.next();
			CanvasView.getInstance().drawHierarchy(hierarchy);
		}
	}

	public void setGraphComponent(mxGraphComponent graphComponent) {
		this.graphComponent = graphComponent;
	}

	public mxGraphComponent getGraphComponent() {
		return graphComponent;
	}

	public void removeComponent(mxCell component2) {
		mxCell c[] = new mxCell[1];
		c[0] = component2;
		CanvasView.getInstance().removeCells(c);
	}

	@SuppressWarnings("rawtypes")
	public void removeComponentFromTree(String diagramName, String name) {
		DefaultTreeModel model = (DefaultTreeModel)this.getTree().getModel();
		DefaultMutableTreeNode parentNode = this.searchNode(diagramName);
		DefaultMutableTreeNode node = null;
		Boolean found = false;
		Enumeration e = parentNode.children();
		while (e.hasMoreElements() && !found) {
			node = (DefaultMutableTreeNode) e.nextElement();
			if (name.equals(node.getUserObject().toString())) {
				found = true;
			}
		}
		if (found){
			parentNode.remove(node);
		}
		model.reload(parentNode);
		
	}

	public void drawHierarchy(Hierarchy h) {
		CanvasView.getInstance().drawHierarchy(h);
	}

	public void disableButtonArea() {
		Component[] com = buttonPanel.getComponents();  
		for (int a = 0; a < com.length; a++) {  
		     com[a].setEnabled(false);  
		}  
	}
	
	public void enableButtonArea(){
		Component[] com = buttonPanel.getComponents();  
		for (int a = 0; a < com.length; a++) {  
		     com[a].setEnabled(true);  
		}
	}

}
